package main.model.hexisland;

import main.model.hexisland.eventprocessor.HexIslandEventProcessorImp;
import main.model.hexisland.location.HexLocation;
import main.model.hexisland.tile.Tile;
import main.model.hexisland.tile.TileSand;
import main.model.hexisland.tile.TileType;

import java.io.File;

/**
 * Created with IntelliJ IDEA.
 * User: gabe
 * Date: 10/06/13
 * Time: 20:19
 * To change this template use File | Settings | File Templates.
 */
public class DefaultHexIsland
        extends HexIslandEventProcessorImp
        implements HexIsland {

    private static final int ISLANDMIN = 10;
    private static final int ISLANDMAX = 50;
    private static final int ISLANDINIT = 10;

    private int q_size = ISLANDINIT;    //Q (columns)
    private int r_size = ISLANDINIT;     //R (rows)

    private Tile[][] islandTiles; //[Q] [R]

    public DefaultHexIsland(){
        this(ISLANDINIT, ISLANDINIT);
    }

    public DefaultHexIsland(int q, int r){
        q_size = q;
        r_size = r;
        clear();
    }

    /**
     * Returns the tile at the provided location.
     * Or null if the location is unavailable.
     * @param hexLocation
     * @return
     */
    public Tile getTile(HexLocation hexLocation){
        if(hexLocation != null) return getTile(hexLocation.getQ(), hexLocation.getR());
        return null;
    }

    /**
     * Returns the tile at the provided location.
     * Or null if the location is unavailable.
     * @param q
     * @param r
     * @return
     */
    public Tile getTile(int q, int r){
        if(0 <= q && 0 <= r && q < q_size && r < r_size){
            if(islandTiles[q][r] == null) islandTiles[q][r] = new TileSand();
            return islandTiles[q][r];
        }
        else return null;
    }

    public void setTile(HexLocation hexLocation, Tile tile) {
        if(hexLocation != null && tile != null) setTile(hexLocation.getQ(), hexLocation.getR(), tile);
    }

    /**
     *
     * @param q
     * @param r
     * @param tile
     */
    public void setTile(int q, int r, Tile tile) {
        if(tile != null
                && 0 <= q && 0 <= r && q < q_size && r < r_size){
            if(getTile(q,r).equals(tile)) return;

            islandTiles[q][r] = tile;
            fireTileChangeEvent(q,r);
        }
    }

    public TileType getTileType(HexLocation hexLocation) {
        if(hexLocation != null) return getTileType(hexLocation.getQ(), hexLocation.getR());
        return null;
    }

    public TileType getTileType(int q, int r) {
        if(0 <= q && 0 <= r && q < q_size && r < r_size){
            if(islandTiles[q][r] == null) return TileType.SAND;
            else return islandTiles[q][r].getType();
        }
        return null;
    }

    public boolean hasCentralObstacle(HexLocation hexLocation) {
        if(hexLocation != null) return hasCentralObstacle(hexLocation.getQ(), hexLocation.getR());
        return true;
    }

    public boolean hasCentralObstacle(int q, int r) {
        if(getTile(q,r) != null) return islandTiles[q][r].hasCentralObstacle();
        return true;
    }


    public boolean isAccessible(HexLocation hexLocation) {
        if(hexLocation != null) return isAccessible(hexLocation.getQ(), hexLocation.getR());
        return false;
    }

    public boolean isAccessible(int q, int r) {
        if(getTile(q,r) != null) return islandTiles[q][r].isAccessible();
        return false;
    }

    public void setSize(int q, int r) {
        if(q == getQSize() && r == getRSize()) return;
        if(q<ISLANDMIN){
            setSize(ISLANDMIN,r);
            return;
        }else if(q>ISLANDMAX){
            setSize(ISLANDMAX,r);
            return;
        }else if(q<ISLANDMIN){
            setSize(r,ISLANDMIN);
            return;
        }else if(q>ISLANDMAX){
            setSize(r,ISLANDMAX);
            return;
        }else{
            Tile[][] islandTemp = new Tile[q][r];
            for(int q_count = 0; q_count < q ; q_count++){
                for(int r_count = 0; r_count < r ; r_count++){
                    if(this.q_size > q_count && this.r_size > r_count){
                        islandTemp[q_count][r_count] = islandTiles[q_count][r_count];
                    }
                }
            }
            islandTiles = islandTemp;

            this.q_size = q;
            this.r_size = r;
            fireIslandChange();
        }
    }

    public int getQSize(){
        return q_size;
    }

    public int getRSize(){
        return r_size;
    }

    @Override
    public int getMinSize() {
        return ISLANDMIN;  //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public int getMaxSize() {
        return ISLANDMAX;  //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public int getDefaultSize() {
        return ISLANDINIT;  //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public File loadedIsland() {
        return null;  //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public void clear() {
        clear(this.q_size , this.r_size);
    }

    @Override
    public void clear(int q , int r) {
        islandTiles = new Tile[q][r];
        fireIslandChange();
    }

    @Override
    public void overWriteIsland(HexIsland newHexIsland) {
        islandTiles = new Tile[newHexIsland.getQSize()][newHexIsland.getRSize()];
        this.q_size = newHexIsland.getQSize();
        this.r_size = newHexIsland.getRSize();

        for(int q = 0; q < q_size; q++){
            for(int r = 0; r < r_size; r++){
                islandTiles[q][r] = newHexIsland.getTile(q,r);
            }
        }
        fireIslandChange();
    }

    @Override
    public void randomize() {
        overWriteIsland(RandomHexIslandCreator.createRandomHexIsland(q_size, r_size));
    }
}
